﻿using System.Reflection;
using System.Text.Json.Serialization;
using Newtonsoft.Json;

namespace Devonline.AspNetCore;

/// <summary>
/// 查询选项
/// </summary>
public class QueryOptions
{
    /// <summary>
    /// 当前表达式的类型主体
    /// </summary>
    private readonly Type _type;

    /// <summary>
    /// 使用原始字符串表达式的构造函数
    /// </summary>
    /// <param name="queryOption"></param>
    public QueryOptions(Type type, QueryOptionRawValue queryOption)
    {
        _type = type;
        Count = queryOption.Count;
        Top = queryOption.Top;
        Skip = queryOption.Skip;

        if (!string.IsNullOrWhiteSpace(queryOption.Filter))
        {
            //TODO TBC
            Filter = new FilterOption(_type, queryOption.Filter);
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Orderby))
        {
            Orderby = new OrderbyOption(_type, queryOption.Orderby);
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Select))
        {
            Select = queryOption.Select.Split(AppSettings.CHAR_COMMA, StringSplitOptions.RemoveEmptyEntries);
            var memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
            var fields = Select.Where(x => !memberInfos.Any(a => x == a.Name)).ToList();
            if (fields.Any())
            {
                throw new ArgumentException($"the properties or fields {fields.ToString<string>()} of type {_type.Name} not found!");
            }
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Expand))
        {
            //TODO expand 功能暂不实现
            Expand = new QueryOptions(_type, new QueryOptionRawValue(queryOption.Expand));
        }
    }

    /// <summary>
    /// 是否返回总数量
    /// </summary>
    [JsonProperty("$count")]
    [JsonPropertyName("$count")]
    public bool? Count { get; set; }
    /// <summary>
    /// 当前页码
    /// </summary>
    [JsonProperty("$top")]
    [JsonPropertyName("$top")]
    public int? Top { get; set; }
    /// <summary>
    /// 页大小
    /// </summary>
    [JsonProperty("$skip")]
    [JsonPropertyName("$skip")]
    public int? Skip { get; set; }
    /// <summary>
    /// 查询/过滤选项
    /// </summary>
    [JsonProperty("$filter")]
    [JsonPropertyName("$filter")]
    public FilterOption? Filter { get; set; }
    /// <summary>
    /// 排序选项
    /// </summary>
    [JsonProperty("$orderby")]
    [JsonPropertyName("$orderby")]
    public OrderbyOption? Orderby { get; set; }
    /// <summary>
    /// 列选项
    /// </summary>
    [JsonProperty("$select")]
    [JsonPropertyName("$select")]
    public IEnumerable<string>? Select { get; set; }
    /// <summary>
    /// 扩展选项
    /// </summary>
    [JsonProperty("$expand")]
    [JsonPropertyName("$expand")]
    public QueryOptions? Expand { get; set; }

    /// <summary>
    /// 重载的 ToString 方法返回 QueryOptions 的字符串表达式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        var result = new List<string>();

        if (Count.HasValue && Count.Value)
        {
            result.Add("$count=true");
        }

        if (Top.HasValue && Top.Value > 0)
        {
            result.Add($"$top={Top.Value}");
        }

        if (Skip.HasValue && Skip.Value > 0)
        {
            result.Add($"$skip={Skip.Value}");
        }

        if (Filter != null)
        {
            result.Add($"$filter={Filter}");
        }

        if (Orderby != null)
        {
            result.Add($"$orderby={Orderby}");
        }

        if (Select != null)
        {
            result.Add($"Select={string.Join(AppSettings.CHAR_COMMA, Select)}");
        }

        if (Expand != null)
        {
            result.Add($"$expand={Expand}");
        }

        return string.Join(AppSettings.CHAR_ADD, result);
    }
}

/// <summary>
/// 查询选项
/// </summary>
public class QueryOptions<T>
{
    /// <summary>
    /// 当前表达式的类型主体
    /// </summary>
    private readonly Type _type = typeof(T);

    /// <summary>
    /// 使用原始字符串表达式的构造函数
    /// </summary>
    /// <param name="queryOption"></param>
    public QueryOptions(QueryOptionRawValue queryOption)
    {
        Count = queryOption.Count;
        Top = queryOption.Top;
        Skip = queryOption.Skip;

        if (!string.IsNullOrWhiteSpace(queryOption.Filter))
        {
            if (NestedFilterOption<T>.LogicExpression.Any(x => queryOption.Filter.Contains(x)))
            {
                Filter = new NestedFilterOption<T>(queryOption.Filter);
            }
            else
            {
                Filter = new FilterOption<T>(queryOption.Filter);
            }
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Orderby))
        {
            Orderby = new OrderbyOption<T>(queryOption.Orderby);
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Select))
        {
            Select = queryOption.Select.Split(AppSettings.CHAR_COMMA, StringSplitOptions.RemoveEmptyEntries);
            var memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
            var fields = Select.Where(x => !memberInfos.Any(a => x.FirstCharToLower() == a.Name.FirstCharToLower())).ToList();
            if (fields.Any())
            {
                throw new ArgumentException($"the properties or fields {fields.ToString<string>()} of type {_type.Name} not found!");
            }
        }

        if (!string.IsNullOrWhiteSpace(queryOption.Expand))
        {
            //TODO expand 功能暂不实现
            Expand = new QueryOptions<T>(new QueryOptionRawValue(queryOption.Expand));
        }
    }

    /// <summary>
    /// 是否返回总数量
    /// </summary>
    [JsonProperty("$count")]
    [JsonPropertyName("$count")]
    public bool? Count { get; set; }
    /// <summary>
    /// 当前页码
    /// </summary>
    [JsonProperty("$top")]
    [JsonPropertyName("$top")]
    public int? Top { get; set; }
    /// <summary>
    /// 页大小
    /// </summary>
    [JsonProperty("$skip")]
    [JsonPropertyName("$skip")]
    public int? Skip { get; set; }
    /// <summary>
    /// 查询/过滤选项
    /// </summary>
    [JsonProperty("$filter")]
    [JsonPropertyName("$filter")]
    public FilterOption<T>? Filter { get; set; }
    /// <summary>
    /// 排序选项
    /// </summary>
    [JsonProperty("$orderby")]
    [JsonPropertyName("$orderby")]
    public OrderbyOption<T>? Orderby { get; set; }
    /// <summary>
    /// 列选项
    /// </summary>
    [JsonProperty("$select")]
    [JsonPropertyName("$select")]
    public IEnumerable<string>? Select { get; set; }
    /// <summary>
    /// 扩展选项
    /// </summary>
    [JsonProperty("$expand")]
    [JsonPropertyName("$expand")]
    public QueryOptions<T>? Expand { get; set; }

    /// <summary>
    /// 重载的 ToString 方法返回 QueryOptions 的字符串表达式
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        var result = new List<string>();

        if (Count.HasValue && Count.Value)
        {
            result.Add("$count=true");
        }

        if (Top.HasValue && Top.Value > 0)
        {
            result.Add($"$top={Top.Value}");
        }

        if (Skip.HasValue && Skip.Value > 0)
        {
            result.Add($"$skip={Skip.Value}");
        }

        if (Filter != null)
        {
            result.Add($"$filter={Filter}");
        }

        if (Orderby != null)
        {
            result.Add($"$orderby={Orderby}");
        }

        if (Select != null)
        {
            result.Add($"Select={string.Join(AppSettings.CHAR_COMMA, Select)}");
        }

        if (Expand != null)
        {
            result.Add($"$expand={Expand}");
        }

        return string.Join(AppSettings.CHAR_ADD, result);
    }
}